using System;
using System.Collections.Generic;
using System.Linq;
using Urs.Core;
using Urs.Core.Caching;
using Urs.Core.Data;
using Urs.Data.Domain.Stores;

namespace Urs.Services.Stores
{
    public partial class GoodsParameterService : IGoodsParameterService
    {
        #region Constants
        private const string GOODSPARAMETER_BY_ID_KEY = "Urs.goodsparameter.id-{0}";
        private const string GOODSPARAMETEROPTION_BY_ID_KEY = "Urs.goodsparameteroptions.id-{0}";
        private const string PRODUCTGOODSPARAMETER_ALLBYPRODUCTID_KEY = "Urs.goodsgoodsparameter.allbygoodsid-{0}-{1}-{2}";
        private const string GOODSPARAMETER_PATTERN_KEY = "Urs.goodsparameters.";
        private const string GOODSPARAMETEROPTION_PATTERN_KEY = "Urs.goodsparameteroptions.";
        private const string PRODUCTGOODSPARAMETER_PATTERN_KEY = "Urs.goodsgoodsparameter.";
        #endregion

        #region Fields
        private readonly IRepository<GoodsParameterGroup> _parameterGroupRepository;
        private readonly IRepository<GoodsParameter> _goodsParameterRepository;
        private readonly IRepository<GoodsParameterOption> _goodsParameterOptionRepository;
        private readonly IRepository<GoodsParameterMapping> _goodsParameterMappingRepository;
        private readonly ICacheManager _cacheManager;

        #endregion

        #region Ctor

        public GoodsParameterService(ICacheManager cacheManager,
            IRepository<GoodsParameterGroup> parameterGroupRepository,
            IRepository<GoodsParameter> goodsParameterRepository,
            IRepository<GoodsParameterOption> goodsParameterOptionRepository,
            IRepository<GoodsParameterMapping> goodsParameterMappingRepository)
        {
            _cacheManager = cacheManager;
            _parameterGroupRepository = parameterGroupRepository;
            _goodsParameterRepository = goodsParameterRepository;
            _goodsParameterOptionRepository = goodsParameterOptionRepository;
            _goodsParameterMappingRepository = goodsParameterMappingRepository;
        }

        #endregion

        #region Methods

        #region Specification group

        public GoodsParameterGroup GetParameterGroupById(int parameterGroupId)
        {
            return _parameterGroupRepository.GetById(parameterGroupId);
        }

        public IList<GoodsParameterGroup> GetAllParameterGroups()
        {
            var query = _parameterGroupRepository.Table;

            query = query.OrderBy(m => m.DisplayOrder);

            var group = query.ToList();
            return group;
        }

        public IPagedList<GoodsParameterGroup> GetParameterGroups(int pageIndex, int pageSize)
        {
            var group = GetAllParameterGroups();
            return new PagedList<GoodsParameterGroup>(group, pageIndex, pageSize);
        }

        public void DeleteParameterGroup(GoodsParameterGroup parameterGroup)
        {
            if (parameterGroup == null)
                throw new ArgumentNullException("parameterGroup");

            _parameterGroupRepository.Delete(parameterGroup);
        }

        public void InsertParameterGroup(GoodsParameterGroup parameterGroup)
        {
            if (parameterGroup == null)
                throw new ArgumentNullException("parameterGroup");

            _parameterGroupRepository.Insert(parameterGroup);
        }

        public void UpdateParameterGroup(GoodsParameterGroup parameterGroup)
        {
            if (parameterGroup == null)
                throw new ArgumentNullException("parameterGroup");

            _parameterGroupRepository.Update(parameterGroup);
        }

        #endregion

        #region Goods parameter

        public virtual GoodsParameter GetGoodsParameterById(int goodsParameterId)
        {
            if (goodsParameterId == 0)
                return null;

            string key = string.Format(GOODSPARAMETER_BY_ID_KEY, goodsParameterId);
            return _cacheManager.Get(key, () =>
            {
                var sa = _goodsParameterRepository.GetById(goodsParameterId);
                return sa;
            });
        }

        public virtual IList<GoodsParameter> GetGoodsParameterList(string name = null, List<int> ids = null)
        {
            var query = _goodsParameterRepository.Table;
            if (ids != null && ids.Count() > 0)
                query = query.Where(q => ids.Contains(q.Id));

            if (!string.IsNullOrEmpty(name))
                query = query.Where(q => q.Name.Contains(name));

            query = query.OrderBy(q => q.DisplayOrder);
            return query.ToList();
        }

        public virtual IPagedList<GoodsParameter> GetGoodsParameters(string name, int groupId, int pageIndex, int pageSize)
        {
            var query = _goodsParameterRepository.Table;

            if (groupId > 0)
                query = query.Where(q => q.GoodsParameterGroupId == groupId);

            if (!string.IsNullOrEmpty(name))
                query = query.Where(q => q.Name.Contains(name));

            query = query.OrderByDescending(q => q.DisplayOrder);

            return new PagedList<GoodsParameter>(query, pageIndex, pageSize);
        }
        public virtual void DeleteGoodsParameter(GoodsParameter goodsParameter)
        {
            if (goodsParameter == null)
                throw new ArgumentNullException("goodsParameter");

            _goodsParameterRepository.Delete(goodsParameter);

            _cacheManager.RemoveByPattern(GOODSPARAMETER_PATTERN_KEY);
            _cacheManager.RemoveByPattern(GOODSPARAMETEROPTION_PATTERN_KEY);
            _cacheManager.RemoveByPattern(PRODUCTGOODSPARAMETER_PATTERN_KEY);

        }

        public virtual void InsertGoodsParameter(GoodsParameter goodsParameter)
        {
            if (goodsParameter == null)
                throw new ArgumentNullException("goodsParameter");

            _goodsParameterRepository.Insert(goodsParameter);

            _cacheManager.RemoveByPattern(GOODSPARAMETER_PATTERN_KEY);
            _cacheManager.RemoveByPattern(GOODSPARAMETEROPTION_PATTERN_KEY);
            _cacheManager.RemoveByPattern(PRODUCTGOODSPARAMETER_PATTERN_KEY);

        }

        public virtual void UpdateGoodsParameter(GoodsParameter goodsParameter)
        {
            if (goodsParameter == null)
                throw new ArgumentNullException("goodsParameter");

            _goodsParameterRepository.Update(goodsParameter);

            _cacheManager.RemoveByPattern(GOODSPARAMETER_PATTERN_KEY);
            _cacheManager.RemoveByPattern(GOODSPARAMETEROPTION_PATTERN_KEY);
            _cacheManager.RemoveByPattern(PRODUCTGOODSPARAMETER_PATTERN_KEY);
        }

        #endregion

        #region Goods parameter option

        public virtual GoodsParameterOption GetGoodsParameterOptionById(int goodsParameterOptionId)
        {
            if (goodsParameterOptionId == 0)
                return null;

            string key = string.Format(GOODSPARAMETEROPTION_BY_ID_KEY, goodsParameterOptionId);
            return _cacheManager.Get(key, () =>
            {
                var sao = _goodsParameterOptionRepository.GetById(goodsParameterOptionId);
                return sao;
            });
        }

        public virtual IList<GoodsParameterOption> GetGoodsParameterOptionsByGoodsParameter(int goodsParameterId)
        {
            var query = from sao in _goodsParameterOptionRepository.Table
                        orderby sao.DisplayOrder
                        where sao.GoodsParameterId == goodsParameterId
                        select sao;
            var goodsParameterOptions = query.ToList();
            return goodsParameterOptions;
        }

        public virtual void DeleteGoodsParameterOption(GoodsParameterOption goodsParameterOption)
        {
            if (goodsParameterOption == null)
                throw new ArgumentNullException("goodsParameterOption");

            _goodsParameterOptionRepository.Delete(goodsParameterOption);

            _cacheManager.RemoveByPattern(GOODSPARAMETER_PATTERN_KEY);
            _cacheManager.RemoveByPattern(GOODSPARAMETEROPTION_PATTERN_KEY);
            _cacheManager.RemoveByPattern(PRODUCTGOODSPARAMETER_PATTERN_KEY);

        }

        public virtual void InsertGoodsParameterOption(GoodsParameterOption goodsParameterOption)
        {
            if (goodsParameterOption == null)
                throw new ArgumentNullException("goodsParameterOption");

            _goodsParameterOptionRepository.Insert(goodsParameterOption);

            _cacheManager.RemoveByPattern(GOODSPARAMETER_PATTERN_KEY);
            _cacheManager.RemoveByPattern(GOODSPARAMETEROPTION_PATTERN_KEY);
            _cacheManager.RemoveByPattern(PRODUCTGOODSPARAMETER_PATTERN_KEY);

        }

        public virtual void UpdateGoodsParameterOption(GoodsParameterOption goodsParameterOption)
        {
            if (goodsParameterOption == null)
                throw new ArgumentNullException("goodsParameterOption");

            _goodsParameterOptionRepository.Update(goodsParameterOption);

            _cacheManager.RemoveByPattern(GOODSPARAMETER_PATTERN_KEY);
            _cacheManager.RemoveByPattern(GOODSPARAMETEROPTION_PATTERN_KEY);
            _cacheManager.RemoveByPattern(PRODUCTGOODSPARAMETER_PATTERN_KEY);
        }

        #endregion

        #region Goods specification attribute

        public virtual void DeleteGoodsParameterMapping(GoodsParameterMapping goodsParameterMapping)
        {
            if (goodsParameterMapping == null)
                throw new ArgumentNullException("goodsParameterMapping");

            _goodsParameterMappingRepository.Delete(goodsParameterMapping);

            _cacheManager.RemoveByPattern(GOODSPARAMETER_PATTERN_KEY);
            _cacheManager.RemoveByPattern(GOODSPARAMETEROPTION_PATTERN_KEY);
            _cacheManager.RemoveByPattern(PRODUCTGOODSPARAMETER_PATTERN_KEY);
        }

        public virtual IList<GoodsParameterMapping> GetGoodsParameterMappingByGoodsId(int goodsId)
        {
            return GetGoodsParameterMappingByGoodsId(goodsId, null, null);
        }

        public virtual IList<GoodsParameterMapping> GetGoodsParameterMappingByGoodsId(int goodsId,
            bool? allowFiltering, bool? showOnGoodsPage)
        {
            string allowFilteringCacheStr = "null";
            if (allowFiltering.HasValue)
                allowFilteringCacheStr = allowFiltering.ToString();
            string showOnGoodsPageCacheStr = "null";
            if (showOnGoodsPage.HasValue)
                showOnGoodsPageCacheStr = showOnGoodsPage.ToString();
            string key = string.Format(PRODUCTGOODSPARAMETER_ALLBYPRODUCTID_KEY, goodsId, allowFilteringCacheStr, showOnGoodsPageCacheStr);

            return _cacheManager.Get(key, () =>
            {
                var query = _goodsParameterMappingRepository.Table;
                query = query.Where(psa => psa.GoodsId == goodsId);
                if (allowFiltering.HasValue)
                    query = query.Where(psa => psa.AllowFiltering == allowFiltering.Value);
                query = query.OrderBy(psa => psa.DisplayOrder);

                var goodsParameterMappings = query.ToList();
                return goodsParameterMappings;
            });
        }

        public virtual GoodsParameterMapping GetGoodsParameterMappingById(int goodsParameterMappingId)
        {
            if (goodsParameterMappingId == 0)
                return null;

            var goodsParameterMapping = _goodsParameterMappingRepository.GetById(goodsParameterMappingId);
            return goodsParameterMapping;
        }

        public virtual void InsertGoodsParameterMapping(GoodsParameterMapping goodsParameterMapping)
        {
            if (goodsParameterMapping == null)
                throw new ArgumentNullException("goodsParameterMapping");

            _goodsParameterMappingRepository.Insert(goodsParameterMapping);

            _cacheManager.RemoveByPattern(GOODSPARAMETER_PATTERN_KEY);
            _cacheManager.RemoveByPattern(GOODSPARAMETEROPTION_PATTERN_KEY);
            _cacheManager.RemoveByPattern(PRODUCTGOODSPARAMETER_PATTERN_KEY);

        }

        public virtual void UpdateGoodsParameterMapping(GoodsParameterMapping goodsParameterMapping)
        {
            if (goodsParameterMapping == null)
                throw new ArgumentNullException("goodsParameterMapping");

            _goodsParameterMappingRepository.Update(goodsParameterMapping);

            _cacheManager.RemoveByPattern(GOODSPARAMETER_PATTERN_KEY);
            _cacheManager.RemoveByPattern(GOODSPARAMETEROPTION_PATTERN_KEY);
            _cacheManager.RemoveByPattern(PRODUCTGOODSPARAMETER_PATTERN_KEY);
        }

        #endregion

        #endregion

    }
}
